package org.tgcloud.group.service.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.tgcloud.group.core.*;
import org.tgcloud.group.core.session.SessionFactory;
import org.tgcloud.group.entity.*;
import org.tgcloud.group.repository.*;
import org.tgcloud.group.web.controller.dto.businessAccount.BusinessPerformanceTimeDTO;
import org.tgcloud.group.web.controller.dto.order.TreeOrderListDTO;
import org.tgcloud.group.web.controller.dto.user.BusinessDTO;
import org.tgcloud.group.web.controller.dto.user.BusinessLevelDTO;
import org.tgcloud.group.web.controller.dto.user.BusinessMonthBasicSalaryGoodsValueListDTO;
import org.tgcloud.group.web.controller.dto.user.BusinessMsgDTO;

import java.math.BigDecimal;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: zhy
 * @create: 2023-09-27 09:14
 * @description:
 */
@Service
public class BusinessManageService {

    @Autowired
    private PasswordHelper passwordHelper;

    @Autowired
    private MjBusinessPersonMapper businessPersonMapper;

    @Autowired
    private MjBusinessTimePriceMapper businessTimePriceMapper;

    @Autowired
    private MjProjectMapper projectMapper;

    @Autowired
    private MjOrderMapper orderMapper;

    @Autowired
    private MjPayrollMapper payrollMapper;

    @Autowired
    private SysLabelValueMapper sysLabelValueMapper;

    @Autowired
    private MjProjectBatchMapper projectBatchMapper;

    @Autowired
    private LogInfoMapper logInfoMapper;


    @Autowired
    private SessionFactory sessionFactory;

    public APPResultMessage getBusinessList(Integer pageNum, Integer pageSize, String keyword, Short status, Date startTime,
                                            Date endTime, Integer gradeId, String area, Short businessType,
                                            Integer departId,Integer groupId,Integer areaId,String roleIds,
                                            Date chooseShowStartMonth, Date chooseShowEndMonth) {
        List<YearMonth> dateList = new ArrayList<>();
        if (chooseShowStartMonth != null && chooseShowEndMonth != null){
            dateList = DateUtil.getMonthListByStartTimeAndEndTime(chooseShowStartMonth, chooseShowEndMonth);
        }
        if (pageNum != null && pageSize != null){
            PageHelper.startPage(pageNum, pageSize);
            List<BusinessDTO> dtos = businessPersonMapper.selectManageList(keyword,status, startTime, endTime, gradeId, area, businessType, departId,groupId,areaId);
            PageInfo<BusinessDTO> tables = new PageInfo<>(dtos);
            for (BusinessDTO dto : tables.getList()) {
                if (StringUtil.isNotBlank(roleIds) && StringUtil.containsString(roleIds.split(","), "56")){
                    dto.setTelephone(StringUtil.isNotBlank(dto.getTelephone()) ? "******" : null);
                }
                if (chooseShowStartMonth != null && chooseShowEndMonth != null){
                    List<BusinessMonthBasicSalaryGoodsValueListDTO> salaryGoodsValueListDTOS = businessTimePriceMapper.selectMonthListByBusinessIdAndTime(dto.getId(), chooseShowStartMonth, chooseShowEndMonth);
                    Map<String, BusinessMonthBasicSalaryGoodsValueListDTO> map = salaryGoodsValueListDTOS.stream()
                            .collect(Collectors.toMap(BusinessMonthBasicSalaryGoodsValueListDTO::getMonthDay, listDTO -> listDTO));
                    dto.setMonthList(map);
                }
            }
            ResultMessage result = ResultMessage.builder().setList(tables.getList())
                    .setData(dateList)
                    .setAllPageNumber(tables.getPages()).setCount(tables.getTotal());
            APPResultMessage<Object, BusinessDTO> message = APPResultMessage.getSuccessMessage();
            message.setResult(result);
            return message;
        }else {
            List<BusinessDTO> dtos = businessPersonMapper.selectManageList(keyword,status, startTime, endTime, gradeId, area, businessType, departId,groupId,areaId);
            for (BusinessDTO dto : dtos) {
                if (StringUtil.isNotBlank(roleIds) && StringUtil.containsString(roleIds.split(","), "56")){
                    dto.setTelephone(StringUtil.isNotBlank(dto.getTelephone()) ? "******" : null);
                }
                if (chooseShowStartMonth != null && chooseShowEndMonth != null){
                    List<BusinessMonthBasicSalaryGoodsValueListDTO> salaryGoodsValueListDTOS = businessTimePriceMapper.selectMonthListByBusinessIdAndTime(dto.getId(), chooseShowStartMonth, chooseShowEndMonth);
                    Map<String, BusinessMonthBasicSalaryGoodsValueListDTO> map = salaryGoodsValueListDTOS.stream()
                            .collect(Collectors.toMap(BusinessMonthBasicSalaryGoodsValueListDTO::getMonthDay, listDTO -> listDTO));
                    dto.setMonthList(map);
                }
            }
            ResultMessage result = ResultMessage.builder().setList(dtos)
                    .setData(dateList);
            APPResultMessage<Object, BusinessDTO> message = APPResultMessage.getSuccessMessage();
            message.setResult(result);
            return message;
        }
    }

    public APPResultMessage doAddBusiness(String username, String telephone, BigDecimal basicSalary, BigDecimal performanceGoodsValue, String internalValue, Integer gradeId,
                                          String area, Date joinTime, short businessType, Integer departId, Integer groupId, Integer teamType,
                                          String performanceTime, String performanceTimeList,
                                          Integer businessAssistantId, String productSelectionUserIds, String customValue) {
        MjBusinessPerson businessPerson = businessPersonMapper.selectMsgByUsername(username);
        if (businessPerson != null){
            return new APPResultMessage(6001, "该商务名字已添加过，请重新添加");
        }
        MjBusinessPerson mjBusinessPerson = new MjBusinessPerson();
        mjBusinessPerson.setUsername(username);
        mjBusinessPerson.setTelephone(telephone);
        mjBusinessPerson.setBasicSalary(basicSalary);
        if (performanceGoodsValue != null){
            mjBusinessPerson.setPerformanceGoodsValue(performanceGoodsValue.toString());
        }
        mjBusinessPerson.setInternalValue(internalValue);
        mjBusinessPerson.setCreateTime(new Date());
        mjBusinessPerson.setStatus((short) 1);
        mjBusinessPerson.setGradeId(gradeId);
        mjBusinessPerson.setArea(area);
        SysLabelValue sysLabelValue = sysLabelValueMapper.selectValueBySysIdAndName(3, area);
        mjBusinessPerson.setAreaId(sysLabelValue.getId());
        mjBusinessPerson.setJoinTime(joinTime);
        mjBusinessPerson.setUpdateTime(new Date());
        mjBusinessPerson.setRoleId("40");
        mjBusinessPerson.setPassword("123456");
        mjBusinessPerson.setBusinessType(businessType);
        mjBusinessPerson.setDepartId(departId);
        // 添加项目经理与选品人
        mjBusinessPerson.setBusinessAssistantId(businessAssistantId);
        mjBusinessPerson.setProductSelectionUserIds(productSelectionUserIds);
        //添加分组信息,1,组长，2,组员
        if (groupId != null && teamType != null){
            //如果要将商务设为组长，判断是否已有组长，之前的所有组内的人设为组员
            if (teamType == 1){
                mjBusinessPerson.setGroupId(groupId);
                List<Integer> idList = businessPersonMapper.judgeTeamLeader(groupId);
                if (idList != null && idList.size() >0){
                    return new APPResultMessage(6001, "该组已有组长");
                }
            } else {
                mjBusinessPerson.setGroupId(groupId);
                mjBusinessPerson.setTeamType(teamType);
            }
        }
        mjBusinessPerson.setCustomValue(customValue);
        passwordHelper.encryptPasswordBusinessUser(mjBusinessPerson);
        businessPersonMapper.insertSelective(mjBusinessPerson);
        doUpdateAddBusinessTime(performanceTimeList, mjBusinessPerson.getId(), basicSalary);
        return APPResultMessage.getSuccessMessage();
    }

    public APPResultMessage doEditBusiness(int businessId, String username, String telephone, BigDecimal basicSalary, BigDecimal performanceGoodsValue, String internalValue,
                                           Integer gradeId, String area, Date joinTime, String password,
                                           Short businessType, Integer departId, Integer groupId, Integer teamType, String performanceTime,
                                           String performanceTimeList,
                                           Integer businessAssistantId, String productSelectionUserIds, String customValue) {
        MjBusinessPerson mjBusinessPerson = new MjBusinessPerson();
        mjBusinessPerson.setId(businessId);
        mjBusinessPerson.setUsername(username);
        mjBusinessPerson.setTelephone(telephone);
        mjBusinessPerson.setBasicSalary(basicSalary);
        mjBusinessPerson.setInternalValue(internalValue);
        mjBusinessPerson.setGradeId(gradeId);
        mjBusinessPerson.setArea(area);
        mjBusinessPerson.setJoinTime(joinTime);
        mjBusinessPerson.setUpdateTime(new Date());
        mjBusinessPerson.setBusinessType(businessType);
        mjBusinessPerson.setDepartId(departId);
        if (performanceGoodsValue != null){
            mjBusinessPerson.setPerformanceGoodsValue(performanceGoodsValue.toString());
        }
        if (StringUtil.isNotBlank(password)){
            mjBusinessPerson.setPassword(password);
            passwordHelper.encryptPasswordBusinessUser(mjBusinessPerson);
        }
        // 添加项目经理与选品人
        if (businessAssistantId != null){
            mjBusinessPerson.setBusinessAssistantId(businessAssistantId);
        }
        if (StringUtil.isNotBlank(productSelectionUserIds)){
            mjBusinessPerson.setProductSelectionUserIds(productSelectionUserIds);
        }
        //添加分组信息,1,组长，2,组员
        if (groupId != null && teamType != null){
            //如果要将商务设为组长，判断是否已有组长，之前的所有组内的人设为组员
            if (teamType == 1) {
                mjBusinessPerson.setGroupId(groupId);
                List<Integer> idList = businessPersonMapper.judgeTeamLeader(groupId);
                if (idList != null && idList.size() > 0) {
                    businessPersonMapper.updateGroupTeamByGroupIdAndId(groupId);
                }
            }
            mjBusinessPerson.setGroupId(groupId);
            mjBusinessPerson.setTeamType(teamType);
        }
        mjBusinessPerson.setCustomValue(customValue);
        doUpdateAddBusinessTime(performanceTimeList, businessId, basicSalary);
        //修改商务信息
        businessPersonMapper.updateByPrimaryKeySelective(mjBusinessPerson);
        projectMapper.updateBusinessUsernameByBusinessId(businessId, username);
        return APPResultMessage.getSuccessMessage();
    }

    public void doUpdateAddBusinessTime(String performanceTimeList, Integer businessId, BigDecimal basicSalary){
        if (StringUtil.isNotBlank(performanceTimeList)){
            List<BusinessPerformanceTimeDTO> list = JSON.parseArray(performanceTimeList, BusinessPerformanceTimeDTO.class);
            for (BusinessPerformanceTimeDTO dto : list){
                if (dto.getTime() != null && dto.getPrice() != null){
                    //查询出对应的月份是否添加了记录
                    MjBusinessTimePrice businessTimePrice = businessTimePriceMapper.selectTaskMsgByBusinessIdAndTime(businessId, new Date(dto.getTime()));
                    if (businessTimePrice != null){
                        //如果已经有，修改绩效
                        businessTimePrice.setPerformanceGoodsPrice(dto.getPrice());
                        businessTimePrice.setBasicSalary(dto.getBasicSalary());
                        businessTimePrice.setUpdateTime(new Date());
                        businessTimePriceMapper.updateByPrimaryKeySelective(businessTimePrice);
                    } else {
                        //如果没有，新增绩效
                        MjBusinessTimePrice timePrice = new MjBusinessTimePrice();
                        timePrice.setBusinessId(businessId);
                        timePrice.setChooseTime(new Date(dto.getTime()));
                        timePrice.setBasicSalary(dto.getBasicSalary());
                        timePrice.setPerformanceGoodsPrice(dto.getPrice());
                        timePrice.setCreateTime(new Date());
                        timePrice.setUpdateTime(new Date());
                        timePrice.setStatus((short) 1);
                        businessTimePriceMapper.insertSelective(timePrice);
                    }
                }
            }
        }
    }

    //比较两个Date的年月是否相等
    public static boolean isSameYearAndMonth(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);

        return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
                cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
    }


    public APPResultMessage doEditBusinessStatus(int businessId, Short status, Date departTime) {
        businessPersonMapper.updateStatusById(businessId, status,departTime);
        //同时修改角色为编外商务
        businessPersonMapper.updateRoleByBusinessId(businessId,55);
        // 将后续年月的绩效全部设置成0
        if (status == 2){
            businessPersonMapper.updateNoBasicSalaryAndGoodValueByBusinessId(businessId);
            //将后续年月的绩效全部设置成0
            businessTimePriceMapper.updatePerformanceGoodsPriceByBusinessId(businessId, departTime);
        }
        //重新登陆
        destroyToken(businessId,null);
        return APPResultMessage.getSuccessMessage();
    }


    public BusinessLevelDTO getBusinessOrder(Integer businessUserId, List<MjProject> projectList, BigDecimal totalBusinessPayPrice,Date time,
                                             Integer useType, String blindOnePrice){
        //时间内的工资
        totalBusinessPayPrice = totalBusinessPayPrice == null ? BigDecimal.ZERO : totalBusinessPayPrice;
        BusinessLevelDTO dto = new BusinessLevelDTO();
        dto.setPayPrice(totalBusinessPayPrice);
        //已成交项目数量
        dto.setHasCommitProjectNum(projectList.size());
        boolean isNullOrder = false;

        // 盲盒收入/盲盒应收
        BigDecimal blindBoxPriceFinal = BigDecimal.ZERO;
        //盲盒实收
        BigDecimal blindRealPriceFinal = BigDecimal.ZERO;
        //项目应收 = 订单去向为渠道竞价的卖货实收 + 其他的订单去向的预计变现
        BigDecimal projectSalePriceFinal = BigDecimal.ZERO;
        //卖货实收 = 订单去向为渠道竞价的卖货实收之和
        BigDecimal projectSaleRealPriceFinal = BigDecimal.ZERO;
        //预计成本
        BigDecimal estimateCostFinal = BigDecimal.ZERO;
        //实际成本
        BigDecimal actualCostFinal = BigDecimal.ZERO;
        //开单总额/项目总货值
        BigDecimal totalPriceFinal = BigDecimal.ZERO;
        //内部货值
        BigDecimal innerPriceFinal = BigDecimal.ZERO;
        //项目实际货值
        BigDecimal projectRealTotalPriceFinal = BigDecimal.ZERO;
        //总成本-根据useType变动
        BigDecimal useTypeTotalCost = BigDecimal.ZERO;
        //总收入-根据useType变动
        BigDecimal useTypeTotalPrice = BigDecimal.ZERO;
        //盲盒收入-根据useType变动
        BigDecimal useTypeBlindTotalPrice = BigDecimal.ZERO;
        //盲盒成本-根据useType变动
        BigDecimal useTypeBlindTotalCost = BigDecimal.ZERO;

        //已签单项目id列表
        List<Integer> hasCheckProjectIds = new ArrayList<>();
        for (MjProject project : projectList){
            List<MjOrder> orders = orderMapper.selectListByProjectId(project.getId());
            if (BeanUtil.isNullList(orders)){
                isNullOrder = true;
            }
            for (MjOrder order : orders){

                // 盲盒收入/盲盒应收
                BigDecimal blindBoxPrice = BigDecimal.ZERO;
                //盲盒实收
                BigDecimal blindRealPrice = BigDecimal.ZERO;
                //项目应收 = 订单去向为渠道竞价的卖货实收 + 其他的订单去向的预计变现
                BigDecimal projectSalePrice = BigDecimal.ZERO;
                //卖货实收 = 订单去向为渠道竞价的卖货实收之和
                BigDecimal projectSaleRealPrice = BigDecimal.ZERO;
                //预计成本
                BigDecimal estimateCost = BigDecimal.ZERO;
                //实际成本
                BigDecimal actualCost = BigDecimal.ZERO;
                //开单总额/项目总货值
                BigDecimal totalPrice = BigDecimal.ZERO;
                //内部货值
                BigDecimal innerPrice = BigDecimal.ZERO;
                //项目实际货值
                BigDecimal projectRealTotalPrice = BigDecimal.ZERO;
                // 盲盒-预计成本
                BigDecimal blindBoxCost = BigDecimal.ZERO;
                //盲盒-实际成本
                BigDecimal blindBoxRealCost = BigDecimal.ZERO;

                //放入id
                if (hasCheckProjectIds.indexOf(order.getProjectId()) == -1){
                    hasCheckProjectIds.add(order.getProjectId());
                }
                //先不找子订单，等查到父订单再计算
                if (ObjUtil.isNotNull(order) && ObjUtil.isNull(order.getParentId())){
                    //筛选有子订单的列表，除了核价卖货应收用父订单的，其他都用子订单累加
                    if ( ObjUtil.isNotNull(order.getIsHasChild()) && order.getIsHasChild() == 2){
                        List<TreeOrderListDTO> childOrderList = orderMapper.selectChildOrder(order.getId());
                        if (CollUtil.isNotEmpty(childOrderList)){
                            for (TreeOrderListDTO childOrder : childOrderList) {
                                if (childOrder.getOrderGo() != null && childOrder.getOrderGo() == 5047){
                                    // 盲盒
                                    //盲盒收入
                                    if (childOrder.getExpectPrice() != null && childOrder.getExpectPrice().compareTo(BigDecimal.ZERO) > 0){
                                        blindBoxPrice = blindBoxPrice.add(childOrder.getExpectPrice());
                                    }else {
                                        if (childOrder.getTotalNum() != null) {
                                            BigDecimal bTotalPrice = new BigDecimal(childOrder.getTotalNum()).multiply(new BigDecimal(blindOnePrice));
                                            blindBoxPrice = blindBoxPrice.add(bTotalPrice);
                                        }
                                    }
                                    //盲盒实收
                                    blindRealPrice = blindRealPrice.add(childOrder.getBlindRealPrice() != null ? childOrder.getBlindRealPrice() : BigDecimal.ZERO);
                                    // 盲盒-预计成本
                                    blindBoxCost = blindBoxCost.add(childOrder.getEstimatedCost() != null ? childOrder.getEstimatedCost() : BigDecimal.ZERO);
                                    //盲盒-实际成本
                                    blindBoxRealCost = blindBoxRealCost.add(childOrder.getActualCost() != null ? childOrder.getActualCost() : BigDecimal.ZERO);
                                }else {
                                    // 其他全部算在易货表单里
                                    //项目应收 = 订单去向为渠道竞价的卖货实收 + 其他的订单去向的预计变现
                                    // （这里没有盲盒应收，最后结算的时候需要手动加上盲盒应收的数据）
                                    if (childOrder.getOrderGo() != null && childOrder.getOrderGo() == 155){
                                        projectSalePrice = projectSalePrice.add(childOrder.getSaleRealPrice() != null ? childOrder.getSaleRealPrice() : BigDecimal.ZERO);
                                    }else {
                                        projectSalePrice = projectSalePrice.add(childOrder.getExpectPrice() != null && childOrder.getExpectPrice().compareTo(BigDecimal.ZERO) > 0 ? childOrder.getExpectPrice() : BigDecimal.ZERO);
                                    }
                                    //卖货实收 = 订单去向为渠道竞价的卖货实收之和
                                    if (childOrder.getOrderGo() != null && childOrder.getOrderGo() == 155){
                                        projectSaleRealPrice = projectSaleRealPrice.add(childOrder.getSaleRealPrice() != null ? childOrder.getSaleRealPrice() : BigDecimal.ZERO);
                                    }
                                }
                                // 预计成本
                                estimateCost = estimateCost.add(childOrder.getEstimatedCost() != null ? childOrder.getEstimatedCost() : BigDecimal.ZERO);
                                // 实际成本
                                actualCost = actualCost.add(childOrder.getActualCost() != null ? childOrder.getActualCost() : BigDecimal.ZERO);
                                // 开单总额/项目总货值
                                totalPrice = totalPrice.add(childOrder.getTotalPrice() != null ? childOrder.getTotalPrice() : BigDecimal.ZERO);
                                // 内部货值
                                innerPrice = innerPrice.add(childOrder.getInnerPrice() != null ? childOrder.getInnerPrice() : BigDecimal.ZERO);
                                // 项目实际货值
                                projectRealTotalPrice = projectRealTotalPrice.add(childOrder.getRealTotalPrice() != null ? childOrder.getRealTotalPrice() : BigDecimal.ZERO);
                            }

                        }
                    } else {
                        if (order.getOrderGo() != null && order.getOrderGo() == 5047){
                            // 盲盒
                            //盲盒收入
                            if (order.getExpectPrice() != null && order.getExpectPrice().compareTo(BigDecimal.ZERO) > 0){
                                blindBoxPrice = blindBoxPrice.add(order.getExpectPrice());
                            }else {
                                if (order.getTotalNum() != null) {
                                    BigDecimal bTotalPrice = new BigDecimal(order.getTotalNum()).multiply(new BigDecimal(blindOnePrice));
                                    blindBoxPrice = blindBoxPrice.add(bTotalPrice);
                                }
                            }
                            //盲盒实收
                            blindRealPrice = blindRealPrice.add(order.getBlindRealPrice() != null ? order.getBlindRealPrice() : BigDecimal.ZERO);
                            // 盲盒-预计成本
                            blindBoxCost = blindBoxCost.add(order.getEstimatedCost() != null ? order.getEstimatedCost() : BigDecimal.ZERO);
                            //盲盒-实际成本
                            blindBoxRealCost = blindBoxRealCost.add(order.getActualCost() != null ? order.getActualCost() : BigDecimal.ZERO);
                        }else {
                            // 其他全部算在易货表单里
                            //项目应收 = 订单去向为渠道竞价的卖货实收 + 其他的订单去向的预计变现
                            if (order.getOrderGo() != null && order.getOrderGo() == 155){
                                projectSalePrice = projectSalePrice.add(order.getSaleRealPrice() != null ? order.getSaleRealPrice() : BigDecimal.ZERO);
                            }else {
                                projectSalePrice = projectSalePrice.add(order.getExpectPrice() != null && order.getExpectPrice().compareTo(BigDecimal.ZERO) > 0 ? order.getExpectPrice() : BigDecimal.ZERO);
                            }
                            //卖货实收 = 订单去向为渠道竞价的卖货实收之和
                            if (order.getOrderGo() != null && order.getOrderGo() == 155){
                                projectSaleRealPrice = projectSaleRealPrice.add(order.getSaleRealPrice() != null ? order.getSaleRealPrice() : BigDecimal.ZERO);
                            }
                        }
                        // 预计成本
                        estimateCost = estimateCost.add(order.getEstimatedCost() != null ? order.getEstimatedCost() : BigDecimal.ZERO);
                        // 实际成本
                        actualCost = actualCost.add(order.getActualCost() != null ? order.getActualCost() : BigDecimal.ZERO);
                        // 开单总额/项目总货值
                        totalPrice = totalPrice.add(order.getTotalPrice() != null ? order.getTotalPrice() : BigDecimal.ZERO);
                        // 内部货值
                        innerPrice = innerPrice.add(order.getInnerPrice() != null ? order.getInnerPrice() : BigDecimal.ZERO);
                        // 项目实际货值
                        projectRealTotalPrice = projectRealTotalPrice.add(order.getRealTotalPrice() != null ? order.getRealTotalPrice() : BigDecimal.ZERO);
                    }
                }


                blindBoxPriceFinal = blindBoxPriceFinal.add(blindBoxPrice);
                blindRealPriceFinal = blindRealPriceFinal.add(blindRealPrice);
                projectSalePriceFinal = projectSalePriceFinal.add(projectSalePrice);
                projectSaleRealPriceFinal = projectSaleRealPriceFinal.add(projectSaleRealPrice);
                estimateCostFinal = estimateCostFinal.add(estimateCost);
                actualCostFinal = actualCostFinal.add(actualCost);
                totalPriceFinal = totalPriceFinal.add(totalPrice);
                innerPriceFinal = innerPriceFinal.add(innerPrice);
                projectRealTotalPriceFinal = projectRealTotalPriceFinal.add(projectRealTotalPrice);

                //计算项目收入，根据useType进行不同的计算
                // 方案1：应收 & 预计成本
                // 方案2：实收 & 预计成本
                // 方案3：实收 & 实际成本
                // 方案4：应收/实收 & 预计成本/实际成本
                BigDecimal addPrice = BigDecimal.ZERO; // 总的应收/实收
                BigDecimal addCost = BigDecimal.ZERO; // 总的成本
                BigDecimal addBlindPrice = BigDecimal.ZERO; // 总的盲盒应收/实收
                if (useType == 1){
                    addPrice = projectSalePrice.add(blindBoxPrice);
                    addCost = estimateCost;
                    addBlindPrice = blindBoxPrice;
                    useTypeBlindTotalCost = blindBoxCost;
                } else if (useType == 2){
                    addPrice = projectSaleRealPrice.add(blindRealPrice);
                    addCost = estimateCost;
                    addBlindPrice = blindRealPrice;
                    useTypeBlindTotalCost = blindBoxCost;
                } else if (useType == 3){
                    addPrice = projectSaleRealPrice.add(blindRealPrice);
                    addCost = actualCost;
                    addBlindPrice = blindRealPrice;
                    useTypeBlindTotalCost = blindBoxRealCost;
                } else {
                    BigDecimal a = projectSaleRealPriceFinal.compareTo(BigDecimal.ZERO) > 0 ? projectSaleRealPriceFinal : projectSalePriceFinal;
                    BigDecimal b = blindRealPriceFinal.compareTo(BigDecimal.ZERO) > 0 ? blindRealPriceFinal : blindBoxPriceFinal;
                    addPrice = a.add(b);
                    addCost = actualCost.compareTo(BigDecimal.ZERO) > 0 ? actualCost : estimateCost;
                    addBlindPrice = b;
                    useTypeBlindTotalCost = blindBoxRealCost.compareTo(BigDecimal.ZERO) > 0 ? blindBoxRealCost : blindBoxCost;
                }
                useTypeTotalPrice = useTypeTotalPrice.add(addPrice);
                useTypeTotalCost = useTypeTotalCost.add(addCost);
                useTypeBlindTotalPrice = useTypeBlindTotalPrice.add(addBlindPrice);
            }
        }
        dto.setBlindPrice(useTypeBlindTotalPrice);
        dto.setBlindRealPrice(blindRealPriceFinal);
        dto.setSalePrice(projectSalePriceFinal);
        dto.setSaleRealPrice(projectSaleRealPriceFinal);
        dto.setEstimatedCost(estimateCostFinal);
        dto.setActualCost(actualCostFinal);
        dto.setTotalPrice(totalPriceFinal);
        dto.setProjectTotalPrice(totalPriceFinal);
        dto.setProjectRealTotalPrice(projectRealTotalPriceFinal);
        dto.setProjectPrice(useTypeTotalPrice);
        dto.setProjectCost(useTypeTotalCost);
        dto.setBlindPrice2(useTypeBlindTotalPrice);
        dto.setInnerPrice(innerPriceFinal);
        if (!BeanUtil.isNullList(projectList) && !isNullOrder){
            // 收入
            // 毛利 = 收入-成本
            BigDecimal price1 = useTypeTotalPrice.subtract(useTypeTotalCost);
            dto.setExpectGrossProfit(price1.compareTo(BigDecimal.ZERO) > 0? price1 : BigDecimal.ZERO);
            // 去盲盒毛利=（项目收入【按方案】-盲盒收入【按方案】）  -  成本【按方案】
            BigDecimal price2 = useTypeTotalPrice.subtract(useTypeBlindTotalPrice).subtract(useTypeTotalCost);
            dto.setNoBlindGrossProfit(price2.compareTo(BigDecimal.ZERO) > 0? price2 : BigDecimal.ZERO);
            // 去工资后利润=毛利-工资
            BigDecimal price3 = dto.getExpectGrossProfit().subtract(dto.getPayPrice());
            dto.setNoPayPriceProfit(price3);
            // 去盲盒去工资后利润=去盲盒毛利-工资
            BigDecimal price4 = dto.getNoBlindGrossProfit().subtract(dto.getPayPrice());
            dto.setNoBlindNoPayPriceProfit(price4);
            //盲盒利润： 盲盒收入-盲盒成本【按方案】
            dto.setBlindBoxRate(useTypeBlindTotalPrice.subtract(useTypeBlindTotalCost));
            // 评级 = 去工资后利润/工资
            if (dto.getPayPrice().compareTo(BigDecimal.ZERO) > 0){
                BigDecimal level = dto.getNoPayPriceProfit().divide(dto.getPayPrice(), 2, BigDecimal.ROUND_HALF_UP);
                dto.setRateLevel(level);
            }else {
                dto.setRateLevel(BigDecimal.ZERO);
            }
        }else {
            dto.setExpectGrossProfit(BigDecimal.ZERO);
            dto.setNoBlindGrossProfit(BigDecimal.ZERO);
            dto.setNoPayPriceProfit(BigDecimal.ZERO);
            dto.setNoBlindNoPayPriceProfit(BigDecimal.ZERO);
            dto.setRateLevel(BigDecimal.ZERO);
            dto.setBlindBoxRate(BigDecimal.ZERO);
        }
        // 已成交的项目数量
        dto.setHasCheckProjectNum(hasCheckProjectIds.size());
        return dto;
    }

    /**
     * @author: zhy
     * @description: 商务业绩
     * @create: 2023年10月23日 09:39
     * @Params totalBusinessPayPrice 工资
     * @Params useType 方案 默认是方案4
     * @return
     */
    public BusinessLevelDTO getBusinessOrderOld(Integer businessUserId, List<MjProject> projectList, BigDecimal totalBusinessPayPrice,Date time,
                                             Integer useType, String blindOnePrice){
//    每个都有预估与实际两个情况
//    去盲盒毛利=卖货应收-项目成本(预估成本)
//    预计毛利=卖货应收+盲盒应收-项目成本(预估成本)
//    去工资后利润=预计毛利-工资--------
//    去盲盒去工资后利润=去盲盒毛利-工资
//
//    等级P=预计毛利/工资
//    p小于1的时候，极差
//    1<=p<3,差
//    3<=p<5，良好
//    p>=5，优秀
        //时间内的工资
        totalBusinessPayPrice = totalBusinessPayPrice == null ? BigDecimal.ZERO : totalBusinessPayPrice;
        BusinessLevelDTO dto = new BusinessLevelDTO();
        dto.setPayPrice(totalBusinessPayPrice);
        //已成交项目数量
        dto.setHasCommitProjectNum(projectList.size());
        boolean isNullOrder = false;
        //盲盒收入
        BigDecimal blindPrice = BigDecimal.ZERO;
        //盲盒实收
        BigDecimal blindRealPrice = BigDecimal.ZERO;
        //项目收入
        BigDecimal salePrice = BigDecimal.ZERO;
        //卖货实收
        BigDecimal saleRealPrice = BigDecimal.ZERO;
        //预计成本
        BigDecimal estimateCost = BigDecimal.ZERO;
        //实际成本
        BigDecimal actualCost = BigDecimal.ZERO;
        //开单总额
        BigDecimal totalPrice = BigDecimal.ZERO;
        //内部货值
        BigDecimal innerPrice = BigDecimal.ZERO;
        //项目货值
        BigDecimal projectTotalPrice = BigDecimal.ZERO;
        //项目实际货值
        BigDecimal projectRealTotalPrice = BigDecimal.ZERO;
        //项目成本
        BigDecimal projectCost2 = BigDecimal.ZERO;
        //项目收入
        BigDecimal projectPrice2 = BigDecimal.ZERO;
        //盲盒收入
        BigDecimal blindPrice2 = BigDecimal.ZERO;
        //已签单项目id列表
        List<Integer> hasCheckProjectIds = new ArrayList<>();
        for (MjProject project : projectList){
            List<MjOrder> orders = orderMapper.selectListByProjectId(project.getId());
            if (BeanUtil.isNullList(orders)){
                isNullOrder = true;
            }
            for (MjOrder order : orders){
                //放入id
                if (hasCheckProjectIds.indexOf(order.getProjectId()) == -1){
                    hasCheckProjectIds.add(order.getProjectId());
                }
                //先不找子订单，等查到父订单再计算
                if (ObjUtil.isNotNull(order) && ObjUtil.isNull(order.getParentId())){
                    //筛选有子订单的列表，除了核价卖货应收用父订单的，其他都用子订单累加
                    if ( ObjUtil.isNotNull(order.getIsHasChild()) && order.getIsHasChild() == 2){
                        //子订单卖货实收
                        BigDecimal orderSealRealPrice = BigDecimal.ZERO;
                        //子订单盲盒收入
                        BigDecimal orderBlindBoxPrice = BigDecimal.ZERO;

                        List<TreeOrderListDTO> childOrderList = orderMapper.selectChildOrder(order.getId());
                        if (CollUtil.isNotEmpty(childOrderList)){
                            for (TreeOrderListDTO childOrder : childOrderList) {
                                //子订单盲盒收入
                                if (ObjUtil.isNotNull(childOrder.getExpectPrice()) && childOrder.getExpectPrice().compareTo(BigDecimal.ZERO) != 0){
                                    //说明走的盲盒
                                    orderBlindBoxPrice = orderBlindBoxPrice.add(childOrder.getExpectPrice());
                                } else if (childOrder.getTotalNum() != null && childOrder.getIsBlindBox() == 2){

                                    orderBlindBoxPrice = orderBlindBoxPrice.add(new BigDecimal(childOrder.getTotalNum()).multiply(new BigDecimal(blindOnePrice)));
                                } else {
                                    //子订单卖货实收
                                    orderSealRealPrice = orderSealRealPrice.add(childOrder.getSaleRealPrice() != null ? childOrder.getSaleRealPrice() : BigDecimal.ZERO);
                                }
                                // 盲盒实收
                                blindRealPrice = blindRealPrice.add(childOrder.getBlindRealPrice() != null ? childOrder.getBlindRealPrice() : BigDecimal.ZERO);
                                // 项目成本 ： 有实际成本用实际，没有用预计
                                if (childOrder.getActualCost() != null && childOrder.getActualCost().compareTo(BigDecimal.ZERO) != 0){
                                    projectCost2 = projectCost2.add(childOrder.getActualCost());
                                } else if (childOrder.getEstimatedCost() != null){
                                    projectCost2 = projectCost2.add(childOrder.getEstimatedCost());
                                }
                                // 预估成本
                                estimateCost = estimateCost.add(childOrder.getEstimatedCost() != null ? childOrder.getEstimatedCost() : BigDecimal.ZERO);
                                // 实际成本
                                actualCost = actualCost.add(childOrder.getActualCost() != null ? childOrder.getActualCost() : BigDecimal.ZERO);
                                // 开单总额
                                totalPrice = totalPrice.add(childOrder.getTotalPrice() != null ? childOrder.getTotalPrice() : BigDecimal.ZERO);
                                // 签单内部货值
                                innerPrice = innerPrice.add(childOrder.getInnerPrice() != null ? childOrder.getInnerPrice() : BigDecimal.ZERO);
                                // 项目货值
                                projectTotalPrice = projectTotalPrice.add(childOrder.getTotalPrice() != null ? childOrder.getTotalPrice() : BigDecimal.ZERO);
                                // 项目实际货值
                                projectRealTotalPrice = projectRealTotalPrice.add(childOrder.getRealTotalPrice() != null ? childOrder.getRealTotalPrice() : BigDecimal.ZERO);
                            }
                            //盲盒收入+卖货收入（实际/核价--核价用父--实际用子）
                            //项目收入
                            if (useType == 1){
                                projectPrice2 = projectPrice2.add(orderBlindBoxPrice).add(order.getCheckCashPrice() != null ? order.getCheckCashPrice() : BigDecimal.ZERO);
                            } else if (useType == 2){
                                projectPrice2 = projectPrice2.add(blindRealPrice).add(orderSealRealPrice);
                            } else if (useType == 3){
                                projectPrice2 = projectPrice2.add(blindRealPrice).add(orderSealRealPrice);
                            } else {
                                projectPrice2 = projectPrice2.add(orderBlindBoxPrice).add(orderSealRealPrice.compareTo(BigDecimal.ZERO) == 0 ? (order.getCheckCashPrice() != null ? order.getCheckCashPrice() : BigDecimal.ZERO) : orderSealRealPrice);
                            }
                            //卖货实收
                            saleRealPrice = saleRealPrice.add(orderSealRealPrice);
                            //盲盒应收
                            blindPrice2 = blindPrice2.add(orderBlindBoxPrice);
                            //卖货应收（父）
                            salePrice = salePrice.add((order.getCheckCashPrice() != null ? order.getCheckCashPrice() : BigDecimal.ZERO));
                        }
                    } else {
                        //盲盒收入（应收）
                        if (ObjUtil.isNotNull(order.getExpectPrice()) && order.getExpectPrice().compareTo(BigDecimal.ZERO) != 0){
                            projectPrice2 = projectPrice2.add(order.getExpectPrice());
                            blindPrice2 = blindPrice2.add(order.getExpectPrice());
                        } else if (order.getTotalNum() != null && order.getIsBlindBox() == 2){
                            projectPrice2 = projectPrice2.add(new BigDecimal(order.getTotalNum()).multiply(new BigDecimal(blindOnePrice)));
                            blindPrice2 = blindPrice2.add(new BigDecimal(order.getTotalNum()).multiply(new BigDecimal(blindOnePrice)));
                        } else {
                            //卖货收入
                            if (order.getSaleRealPrice() != null && order.getSaleRealPrice().compareTo(BigDecimal.ZERO) != 0){
                                //卖货实收
                                saleRealPrice = saleRealPrice.add(order.getSaleRealPrice());
                                projectPrice2 = projectPrice2.add(order.getSaleRealPrice());
                            } else {
                                // 卖货应收
                                salePrice = salePrice.add(order.getCheckCashPrice() != null ? order.getCheckCashPrice() : BigDecimal.ZERO);
                                projectPrice2 = projectPrice2.add(order.getCheckCashPrice() != null ? order.getCheckCashPrice() : BigDecimal.ZERO);
                            }
                        }
                        //盲盒实收
                        blindRealPrice = blindRealPrice.add(order.getBlindRealPrice() != null ? order.getBlindRealPrice() : BigDecimal.ZERO);
                        // 项目成本 ： 有实际成本用实际，没有用预计
                        if (order.getActualCost() != null && order.getActualCost().compareTo(BigDecimal.ZERO) != 0){
                            projectCost2 = projectCost2.add(order.getActualCost());
                        } else if (order.getEstimatedCost() != null){
                            projectCost2 = projectCost2.add(order.getEstimatedCost());
                        }
                        // 预估成本
                        estimateCost = estimateCost.add(order.getEstimatedCost() != null ? order.getEstimatedCost() : BigDecimal.ZERO);
                        // 实际成本
                        actualCost = actualCost.add(order.getActualCost() != null ? order.getActualCost() : BigDecimal.ZERO);
                        // 开单总额
                        totalPrice = totalPrice.add(order.getTotalPrice() != null ? order.getTotalPrice() : BigDecimal.ZERO);
                        // 签单内部货值
                        innerPrice = innerPrice.add(order.getInnerPrice() != null ? order.getInnerPrice() : BigDecimal.ZERO);
                        // 项目货值
                        projectTotalPrice = projectTotalPrice.add(order.getTotalPrice() != null ? order.getTotalPrice() : BigDecimal.ZERO);
                        // 项目实际货值
                        projectRealTotalPrice = projectRealTotalPrice.add(order.getRealTotalPrice() != null ? order.getRealTotalPrice() : BigDecimal.ZERO);
                    }
                }

            }
        }
        dto.setBlindPrice(blindPrice2);
        dto.setBlindRealPrice(blindRealPrice);
        dto.setSalePrice(salePrice);
        dto.setSaleRealPrice(saleRealPrice);
        dto.setEstimatedCost(estimateCost);
        dto.setActualCost(actualCost);
        dto.setTotalPrice(totalPrice);
        dto.setProjectTotalPrice(projectTotalPrice);
        dto.setProjectRealTotalPrice(projectRealTotalPrice);
        dto.setProjectPrice(projectPrice2);
        dto.setProjectCost(projectCost2);
        dto.setBlindPrice2(blindPrice2);
        dto.setInnerPrice( innerPrice );
        if (!BeanUtil.isNullList(projectList) && !isNullOrder){
            // 收入
            // 毛利 = 收入-成本
            BigDecimal price1 = projectPrice2.subtract(projectCost2);
            dto.setExpectGrossProfit(price1.compareTo(BigDecimal.ZERO) > 0? price1 : BigDecimal.ZERO);
            // 去盲盒预计毛利=卖货应收-项目成本(预估成本)
            BigDecimal price2 = dto.getSalePrice().subtract(dto.getEstimatedCost());
            dto.setNoBlindGrossProfit(price2.compareTo(BigDecimal.ZERO) > 0? price2 : BigDecimal.ZERO);
            // 去工资后利润=毛利-工资
            BigDecimal price3 = dto.getExpectGrossProfit().subtract(dto.getPayPrice());
            dto.setNoPayPriceProfit(price3);
            // 去盲盒去工资后预计利润=去盲盒毛利-工资
            BigDecimal price4 = dto.getNoBlindGrossProfit().subtract(dto.getPayPrice());
            dto.setNoBlindNoPayPriceProfit(price4);
            //盲盒利润： 盲盒收入-预估成本
            dto.setBlindBoxRate(blindPrice2.subtract(estimateCost).compareTo(BigDecimal.ZERO) > 0 ? blindPrice.subtract(estimateCost) : BigDecimal.ZERO);
            // 评级 = 去工资后利润/工资
            if (dto.getPayPrice().compareTo(BigDecimal.ZERO) > 0){
                BigDecimal level = dto.getNoPayPriceProfit().divide(dto.getPayPrice(), 2, BigDecimal.ROUND_HALF_UP);
                dto.setRateLevel(level);
            }else {
                dto.setRateLevel(BigDecimal.ZERO);
            }
        }else {
            dto.setExpectGrossProfit(BigDecimal.ZERO);
            dto.setNoBlindGrossProfit(BigDecimal.ZERO);
            dto.setNoPayPriceProfit(BigDecimal.ZERO);
            dto.setNoBlindNoPayPriceProfit(BigDecimal.ZERO);
            dto.setRateLevel(BigDecimal.ZERO);
            dto.setBlindBoxRate(BigDecimal.ZERO);
        }
        // 已成交的项目数量
        dto.setHasCheckProjectNum(hasCheckProjectIds.size());
        return dto;
    }


    public APPResultMessage doGetBusinessMsg(Date startTime, Date endTime, int businessId) {
        BusinessMsgDTO dto = businessPersonMapper.selectMsgById(businessId);
        BigDecimal payPrice = payrollMapper.selectPayPriceByUsername(dto.getUsername(), startTime, endTime);
        dto.setPayPrice(payPrice);
        List<MjProject> mjProjects = projectMapper.selectListByBusinessIdAndTime(businessId, startTime, endTime);
        String blindOnePrice = sysLabelValueMapper.selectValueBySysIdAndReadOne(9);
        BusinessLevelDTO levelDTO = getBusinessOrder(businessId, mjProjects, dto.getPayPrice(),null, 4, blindOnePrice);
        BeanUtils.copyProperties(levelDTO, dto);
        APPResultMessage successMessage = APPResultMessage.getSuccessMessage();
        ResultMessage resultMessage = ResultMessage.builder().setData(dto);
        successMessage.setResult(resultMessage);
        return successMessage;
    }

    public APPResultMessage doEditResetBusinessPassword(int businessId) {
        MjBusinessPerson businessPerson = businessPersonMapper.selectByPrimaryKey(businessId);
        businessPerson.setPassword("123456");
        passwordHelper.encryptPasswordBusinessUser(businessPerson);
        businessPersonMapper.updateByPrimaryKeySelective(businessPerson);
        return APPResultMessage.getSuccessMessage();
    }

    public APPResultMessage selectPerformanceList(Integer pageNum, Integer pageSize, Integer businessId) {
        if (pageNum != null && pageSize != null){
            PageHelper.startPage(pageNum, pageSize);
            List<MjBusinessTimePrice> mjBusinessTimePrices = businessTimePriceMapper.selectPerformanceList(businessId);
            PageInfo<MjBusinessTimePrice> tables = new PageInfo<>(mjBusinessTimePrices);
            ResultMessage result = ResultMessage.builder().setList(tables.getList()).setAllPageNumber(tables.getPages()).setCount(tables.getTotal());
            APPResultMessage<Object, BusinessDTO> message = APPResultMessage.getSuccessMessage();
            message.setResult(result);
            return message;
        }else {
            List<MjBusinessTimePrice> mjBusinessTimePrices = businessTimePriceMapper.selectPerformanceList(businessId);
            ResultMessage result = ResultMessage.builder().setList(mjBusinessTimePrices);
            APPResultMessage<Object, BusinessDTO> message = APPResultMessage.getSuccessMessage();
            message.setResult(result);
            return message;
        }

    }

    @Async
    public void destroyToken(Integer userId, Integer roleId) {
        if (userId != null) {
            LogInfo logInfo = logInfoMapper.selectByUserId(userId);
            if (logInfo != null) {
                sessionFactory.destroySession(logInfo.getToken());
            }
        }
        if (roleId != null) {
            List<LogInfo> logInfos = logInfoMapper.selectListByRoleId(roleId);
            if (!BeanUtil.isNullList(logInfos)) {
                for (LogInfo info : logInfos) {
                    sessionFactory.destroySession(info.getToken());
                }
            }
        }
    }

    public APPResultMessage doAddPerformanceList(int businessId, String performanceTimeList) {
        MjBusinessPerson mjBusinessPerson = businessPersonMapper.selectByPrimaryKey(businessId);
        doUpdateAddBusinessTime(performanceTimeList, businessId, mjBusinessPerson.getBasicSalary());
        return APPResultMessage.getSuccessMessage();
    }
}
